package cn.org.itool.ws.template;

import cn.hutool.core.net.url.UrlQuery;
import cn.org.itool.common.component.AESComponent;
import cn.org.itool.common.constent.WsCodeEnum;
import cn.org.itool.ws.framework.netty.auth.Principal;
import cn.org.itool.ws.framework.utils.ChannelGroupUtil;
import cn.org.itool.ws.framework.utils.ChannelUtils;
import cn.org.itool.ws.framework.utils.ObjectJsonUtil;
import cn.org.itool.ws.pojo.Auth;
import io.netty.channel.Channel;
import jakarta.annotation.Resource;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.Optional;

@Log4j2
@Service
public class AuthTemplate {

    @Resource
    private AESComponent aesComponent;

    @Resource
    private WsLoginTemplate wsLoginComponent;

    public Optional<Principal> getOptional(String url){
        Optional<Principal> principalOpt;
        try{
            UrlQuery formQuery = new UrlQuery().parse(url, StandardCharsets.UTF_8);
            Object authObj = formQuery.get("auth");
            if(Objects.isNull(authObj)) {
                return Optional.empty();
            }
            String auth = authObj.toString();
            if(StringUtils.isBlank(auth)) {
                return Optional.empty();
            }
            String authStr = aesComponent.decrypt(auth);
            Auth authVO = ObjectJsonUtil.fromJson(authStr, Auth.class);
            if(Objects.isNull(authVO)) {
                return Optional.empty();
            }
            String userId = wsLoginComponent.getUserIdByToken(authVO.getToken());
            return auth(userId, authVO.getGroupName());
        }catch (Exception e){
            log.error("e:", e);
            log.error("User authorization fail url={}, throw={}", url, e.getMessage());
            principalOpt = Optional.empty();
        }
        return principalOpt;
    }

    public void bindUser(Optional<Principal> principalOpt, Channel channel) {
        if(principalOpt.isPresent()) {
            Principal principal = principalOpt.get();
            if(ChannelUtils.setPrincipal(channel, principal) && ChannelGroupUtil.addToGroup(principal, channel)){
                String ip = ChannelUtils.getClientIp(channel);
                String wsId = channel.id().asLongText();
                log.debug("User ip userId={}, wsId={}, ip={}", principal.getId(), wsId, ip);

            }else{
                log.error("add channel to channel group fail");
                ChannelUtils.close(channel, WsCodeEnum.SYS_BUSY);
            }
        }
    }

    public Optional<Principal> auth(String userId, String groupName){
        Optional<Principal> principalOpt;
        try{
            Principal principal = new Principal(userId, groupName, null);
            return Optional.of(principal);
        }catch (Exception e){
            log.error("e:", e);
            principalOpt = Optional.empty();
        }
        return principalOpt;
    }
}
